package com.atguigu.gmall.activity.receiver;

import com.atguigu.gmall.activity.mapper.SeckillGoodsMapper;
import com.atguigu.gmall.activity.service.SeckillGoodsService;
import com.atguigu.gmall.common.constant.MqConst;
import com.atguigu.gmall.common.constant.RedisConst;
import com.atguigu.gmall.common.util.DateUtil;
import com.atguigu.gmall.model.activity.SeckillGoods;
import com.atguigu.gmall.model.activity.UserRecode;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.rabbitmq.client.Channel;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.util.Collection;
import java.util.Date;
import java.util.List;

/**
 * @Author atguigu-mqx
 * @Description TODO
 * @Date 2023/9/8 15:15
 * @Version 1.0
 */
@Component
@Slf4j
public class SeckillReceiver {

    @Autowired
    private SeckillGoodsMapper seckillGoodsMapper;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private SeckillGoodsService seckillGoodsService;


    /**
     * 监听商品数据，实现预热功能
     */
    @SneakyThrows
    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(value = MqConst.QUEUE_TASK_1,durable = "true",autoDelete = "false"),
            exchange = @Exchange(value = MqConst.EXCHANGE_DIRECT_TASK),
            key = {MqConst.ROUTING_TASK_1}
    ))
    public void importDataToRedis(String msg, Message message , Channel channel){
        //  先要查询当天要秒杀的数据： new Date(); 剩余库存数 >0 审核条件:status=1
        /*
        select *
            from seckill_goods
            where date_format(start_time, '%Y-%m-%d') = date_format(now(), '%Y-%m-%d') and status = '1' and stock_count > 0;
         */
        try {
            LambdaQueryWrapper<SeckillGoods> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(SeckillGoods::getStatus,"1");
            wrapper.gt(SeckillGoods::getStockCount,0);
            wrapper.apply("DATE_FORMAT(start_time,'%Y-%m-%d') = " + "'" + DateUtil.formatDate(new Date()) + "'");
            List<SeckillGoods> seckillGoodsList = seckillGoodsMapper.selectList(wrapper);

            //  商品放入缓存。
            if (!CollectionUtils.isEmpty(seckillGoodsList)){
                //  循环遍历。
                for (SeckillGoods seckillGoods : seckillGoodsList) {
                    //  声明缓存的key
                    String SeckillKey = RedisConst.SECKILL_GOODS;
                    //  防止消息重复消费，将数据覆盖。
                    Boolean result = this.redisTemplate.opsForHash().hasKey(SeckillKey, seckillGoods.getSkuId().toString());
                    if (result){
                        //  需要停止当前操作.  return; break;
                        continue;
                    }
                    //  将数据放入缓存.
                    redisTemplate.opsForHash().put(SeckillKey,seckillGoods.getSkuId().toString(),seckillGoods);
                    //  为了防止超卖，将商品的剩余库存数放入redis - list 10
                    for (Integer i = 0; i < seckillGoods.getStockCount(); i++) {
                        //  lpush key value  seckill:stock:skuId  skuId
                        this.redisTemplate.opsForList().leftPush(RedisConst.SECKILL_STOCK_PREFIX+seckillGoods.getSkuId(),seckillGoods.getSkuId().toString());
                    }
                    //  初始化状态位：
                    this.redisTemplate.convertAndSend("seckillpush",seckillGoods.getSkuId()+":1");
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        //  手动确认
        channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
    }

    /**
     * 监听秒杀预下单
     * @param userRecode
     * @param message
     * @param channel
     */
    @SneakyThrows
    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(value = MqConst.QUEUE_SECKILL_USER,durable = "true",autoDelete = "false"),
            exchange = @Exchange(value = MqConst.EXCHANGE_DIRECT_SECKILL_USER),
            key = {MqConst.ROUTING_SECKILL_USER}
    ))
    public void seckillUser(UserRecode userRecode,Message message, Channel channel){
        try {
            //  判断
            if (null != userRecode){
                //  调用服务层方法，实现预下单业务逻辑
                this.seckillGoodsService.seckillUser(userRecode);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        //  手动签收
        channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
    }

    /**
     * 监听秒杀预下单
     * @param userRecode
     * @param message
     * @param channel
     */
    @SneakyThrows
    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(value = MqConst.QUEUE_SECKILL_STOCK,durable = "true",autoDelete = "false"),
            exchange = @Exchange(value = MqConst.EXCHANGE_DIRECT_SECKILL_STOCK),
            key = {MqConst.ROUTING_SECKILL_STOCK}
    ))
    public void seckillStock(Long skuId,Message message, Channel channel){
        try {
            //  判断
            if (null != skuId){
                //  调用服务层方法，实现减库存！
                this.seckillGoodsService.seckillStock(skuId);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        //  手动签收
        channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
    }

    @SneakyThrows
    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(value = MqConst.QUEUE_TASK_18,durable = "true",autoDelete = "false"),
            exchange = @Exchange(value = MqConst.EXCHANGE_DIRECT_TASK),
            key = {MqConst.ROUTING_TASK_18}
    ))
    public void clearData(String msg, Message message , Channel channel){
        try {
            //  考虑清空哪些数据?
            LambdaQueryWrapper<SeckillGoods> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(SeckillGoods::getStatus,"1");
            //  new date();16:10 endTime(); 16:00
            wrapper.le(SeckillGoods::getEndTime,new Date());
            List<SeckillGoods> seckillGoodsList = seckillGoodsMapper.selectList(wrapper);
            //  查询到当前要结束的秒杀商品列表.
            if (!CollectionUtils.isEmpty(seckillGoodsList)){
                //  删除数据
                for (SeckillGoods seckillGoods : seckillGoodsList) {
                    //  删除商品剩余库存数
                    this.redisTemplate.delete(RedisConst.SECKILL_STOCK_PREFIX+seckillGoods.getSkuId());
                }

                //  删除所有秒杀商品
                this.redisTemplate.delete(RedisConst.SECKILL_GOODS);
                //  删除预下单数据
                this.redisTemplate.delete(RedisConst.SECKILL_ORDERS);
                //  删除真正下单数据
                this.redisTemplate.delete(RedisConst.SECKILL_ORDERS_USERS);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        //  手动签收
        channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);

    }
}
